﻿import arcade
import random
import math

# 游戏常量
SCREEN_WIDTH = 1000
SCREEN_HEIGHT = 650
SCREEN_TITLE = "平台跳跃冒险"

# 玩家常量
PLAYER_MOVEMENT_SPEED = 5
PLAYER_JUMP_SPEED = 15
GRAVITY = 0.8

# 缩放因子
SPRITE_SCALING = 0.5
TILE_SCALING = 0.5

class Player(arcade.Sprite):
    def __init__(self):
        super().__init__()
        
        # 加载玩家精灵表
        self.textures = []
        
        # 站立动画
        for i in range(4):
            texture = arcade.load_texture(f"images/player_stand_{i}.png")
            self.textures.append(texture)
        
        # 行走动画
        for i in range(6):
            texture = arcade.load_texture(f"images/player_walk_{i}.png")
            self.textures.append(texture)
        
        # 跳跃动画
        for i in range(3):
            texture = arcade.load_texture(f"images/player_jump_{i}.png")
            self.textures.append(texture)
        
        self.texture = self.textures[0]  # 初始纹理
        self.scale = SPRITE_SCALING
        
        # 动画状态
        self.current_frame = 0
        self.animation_speed = 0.2
        self.time_since_last_frame = 0
        self.facing_right = True
        
        # 物理属性
        self.change_x = 0
        self.change_y = 0
        self.on_ground = False
    
    def update_animation(self, delta_time):
        """更新玩家动画"""
        self.time_since_last_frame += delta_time
        
        if self.time_since_last_frame >= self.animation_speed:
            self.time_since_last_frame = 0
            self.current_frame = (self.current_frame + 1) % 4
            
            if self.change_y != 0:  # 跳跃或下落
                self.texture = self.textures[10 + min(2, self.current_frame // 2)]
            elif self.change_x != 0:  # 行走
                self.texture = self.textures[4 + self.current_frame]
                # 根据方向翻转纹理
                if self.change_x > 0 and not self.facing_right:
                    self.facing_right = True
                    self.texture = arcade.load_texture(
                        self.texture.name, flipped_horizontally=False
                    )
                elif self.change_x < 0 and self.facing_right:
                    self.facing_right = False
                    self.texture = arcade.load_texture(
                        self.texture.name, flipped_horizontally=True
                    )
            else:  # 站立
                self.texture = self.textures[self.current_frame]
    
    def update(self):
        """更新玩家位置"""
        # 应用重力
        self.change_y -= GRAVITY
        
        # 更新位置
        self.center_x += self.change_x
        self.center_y += self.change_y
        
        # 边界检查
        if self.left < 0:
            self.left = 0
        elif self.right > SCREEN_WIDTH:
            self.right = SCREEN_WIDTH
        
        if self.bottom < 0:
            self.bottom = 0
            self.change_y = 0
            self.on_ground = True

class Enemy(arcade.Sprite):
    def __init__(self, x, y):
        super().__init__("images/enemy.png", SPRITE_SCALING)
        self.center_x = x
        self.center_y = y
        self.change_x = random.choice([-2, 2])
        self.boundary_left = x - 100
        self.boundary_right = x + 100
    
    def update(self):
        """更新敌人位置"""
        self.center_x += self.change_x
        
        # 边界检查
        if self.center_x <= self.boundary_left:
            self.change_x *= -1
        elif self.center_x >= self.boundary_right:
            self.change_x *= -1

class Coin(arcade.Sprite):
    def __init__(self, x, y):
        super().__init__("images/coin.png", SPRITE_SCALING * 0.7)
        self.center_x = x
        self.center_y = y
        
        # 旋转动画
        self.angle = 0
        self.rotation_speed = 2
    
    def update(self):
        """更新硬币旋转"""
        self.angle += self.rotation_speed
        if self.angle >= 360:
            self.angle = 0

class PlatformerGame(arcade.Window):
    def __init__(self):
        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
        
        # 场景相关
        self.scene = None
        self.player_sprite = None
        self.physics_engine = None
        
        # 相机
        self.camera = None
        self.gui_camera = None
        
        # 游戏状态
        self.score = 0
        self.level = 1
        self.game_over = False
        self.win = False
        
        # 加载声音
        self.collect_coin_sound = arcade.load_sound("sounds/coin1.wav")
        self.jump_sound = arcade.load_sound("sounds/jump1.wav")
        self.game_over_sound = arcade.load_sound("sounds/gameover1.wav")
        self.win_sound = arcade.load_sound("sounds/win1.wav")
        
        # 设置背景颜色
        arcade.set_background_color(arcade.color.SKY_BLUE)
    
    def setup_level(self, level):
        """设置游戏关卡"""
        # 初始化场景
        self.scene = arcade.Scene()
        
        # 创建精灵列表
        self.scene.add_sprite_list("Player")
        self.scene.add_sprite_list("Walls", use_spatial_hash=True)
        self.scene.add_sprite_list("Coins", use_spatial_hash=True)
        self.scene.add_sprite_list("Enemies")
        self.scene.add_sprite_list("Ladders", use_spatial_hash=True)
        
        # 创建玩家
        self.player_sprite = Player()
        self.player_sprite.center_x = 64
        self.player_sprite.center_y = 128
        self.scene.add_sprite("Player", self.player_sprite)
        
        # 创建地图
        self.create_map(level)
        
        # 创建物理引擎
        self.physics_engine = arcade.PhysicsEnginePlatformer(
            self.player_sprite,
            gravity_constant=GRAVITY,
            walls=self.scene["Walls"],
            ladders=self.scene["Ladders"]
        )
        
        # 设置相机
        self.camera = arcade.Camera(self.width, self.height)
        self.gui_camera = arcade.Camera(self.width, self.height)
    
    def create_map(self, level):
        """创建关卡地图"""
        # 创建平台和墙壁
        for x in range(0, SCREEN_WIDTH * 2, 64):
            # 地面
            wall = arcade.Sprite("images/grassMid.png", TILE_SCALING)
            wall.center_x = x
            wall.center_y = 32
            self.scene.add_sprite("Walls", wall)
        
        # 根据关卡创建不同的地图布局
        if level == 1:
            # 关卡1：简单平台
            platforms = [
                (300, 200, 3), (500, 300, 2), (700, 400, 3),
                (900, 500, 2), (1100, 400, 3), (1300, 300, 2)
            ]
            
            for x, y, length in platforms:
                for i in range(length):
                    platform = arcade.Sprite("images/grassMid.png", TILE_SCALING)
                    platform.center_x = x + i * 64
                    platform.center_y = y
                    self.scene.add_sprite("Walls", platform)
            
            # 添加硬币
            for i in range(20):
                coin = Coin(
                    random.randint(100, SCREEN_WIDTH * 2 - 100),
                    random.randint(100, 500)
                )
                self.scene.add_sprite("Coins", coin)
            
            # 添加敌人
            for i in range(3):
                enemy = Enemy(
                    random.randint(200, SCREEN_WIDTH * 2 - 200),
                    random.randint(100, 300)
                )
                self.scene.add_sprite("Enemies", enemy)
        
        elif level == 2:
            # 关卡2：更复杂的布局
            # 这里可以添加更复杂的地图设计
            pass
    
    def on_draw(self):
        """渲染游戏"""
        arcade.start_render()
        
        # 激活游戏相机
        self.camera.use()
        
        # 绘制所有精灵
        self.scene.draw()
        
        # 激活GUI相机
        self.gui_camera.use()
        
        # 绘制UI
        arcade.draw_text(
            f"分数: {self.score}",
            10, 10,
            arcade.color.WHITE, 24
        )
        
        arcade.draw_text(
            f"关卡: {self.level}",
            SCREEN_WIDTH - 150, 10,
            arcade.color.WHITE, 24
        )
        
        # 游戏结束或胜利画面
        if self.game_over:
            arcade.draw_rectangle_filled(
                SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2,
                SCREEN_WIDTH, SCREEN_HEIGHT,
                (0, 0, 0, 200)
            )
            
            arcade.draw_text(
                "游戏结束!",
                SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 50,
                arcade.color.RED, 50,
                anchor_x="center", anchor_y="center"
            )
            
            arcade.draw_text(
                f"最终分数: {self.score}",
                SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2,
                arcade.color.WHITE, 30,
                anchor_x="center", anchor_y="center"
            )
            
            arcade.draw_text(
                "按R键重新开始",
                SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 50,
                arcade.color.WHITE, 24,
                anchor_x="center", anchor_y="center"
            )
        
        elif self.win:
            arcade.draw_rectangle_filled(
                SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2,
                SCREEN_WIDTH, SCREEN_HEIGHT,
                (0, 0, 0, 200)
            )
            
            arcade.draw_text(
                "恭喜通关!",
                SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 + 50,
                arcade.color.GOLD, 50,
                anchor_x="center", anchor_y="center"
            )
            
            arcade.draw_text(
                f"总分: {self.score}",
                SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2,
                arcade.color.WHITE, 30,
                anchor_x="center", anchor_y="center"
            )
            
            arcade.draw_text(
                "按R键重新开始",
                SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2 - 50,
                arcade.color.WHITE, 24,
                anchor_x="center", anchor_y="center"
            )
    
    def on_update(self, delta_time):
        """游戏逻辑更新"""
        if self.game_over or self.win:
            return
        
        # 更新物理引擎
        self.physics_engine.update()
        
        # 更新玩家动画
        self.player_sprite.update_animation(delta_time)
        
        # 更新敌人
        self.scene.update(["Enemies"])
        
        # 更新硬币
        self.scene.update(["Coins"])
        
        # 检测硬币碰撞
        coin_hit_list = arcade.check_for_collision_with_list(
            self.player_sprite, self.scene["Coins"]
        )
        for coin in coin_hit_list:
            coin.remove_from_sprite_lists()
            self.score += 10
            arcade.play_sound(self.collect_coin_sound)
        
        # 检测敌人碰撞
        enemy_hit_list = arcade.check_for_collision_with_list(
            self.player_sprite, self.scene["Enemies"]
        )
        if enemy_hit_list:
            self.game_over = True
            arcade.play_sound(self.game_over_sound)
        
        # 相机跟随玩家
        self.center_camera_to_player()
        
        # 检查是否通关
        if self.player_sprite.center_x > SCREEN_WIDTH * 2 - 100:
            if self.level < 2:  # 假设有2个关卡
                self.level += 1
                self.setup_level(self.level)
            else:
                self.win = True
                arcade.play_sound(self.win_sound)
    
    def center_camera_to_player(self):
        """相机跟随玩家"""
        screen_center_x = self.player_sprite.center_x - (self.camera.viewport_width / 2)
        screen_center_y = self.player_sprite.center_y - (self.camera.viewport_height / 2)
        
        # 确保相机不会显示地图之外的内容
        if screen_center_x < 0:
            screen_center_x = 0
        if screen_center_y < 0:
            screen_center_y = 0
        
        player_centered = screen_center_x, screen_center_y
        self.camera.move_to(player_centered)
    
    def on_key_press(self, key, modifiers):
        """按键处理"""
        if key == arcade.key.UP or key == arcade.key.W or key == arcade.key.SPACE:
            if self.physics_engine.can_jump():
                self.player_sprite.change_y = PLAYER_JUMP_SPEED
                arcade.play_sound(self.jump_sound)
        elif key == arcade.key.LEFT or key == arcade.key.A:
            self.player_sprite.change_x = -PLAYER_MOVEMENT_SPEED
        elif key == arcade.key.RIGHT or key == arcade.key.D:
            self.player_sprite.change_x = PLAYER_MOVEMENT_SPEED
        elif key == arcade.key.R:
            if self.game_over or self.win:
                self.setup_level(1)
                self.score = 0
                self.level = 1
                self.game_over = False
                self.win = False
    
    def on_key_release(self, key, modifiers):
        """按键释放处理"""
        if key == arcade.key.LEFT or key == arcade.key.A:
            self.player_sprite.change_x = 0
        elif key == arcade.key.RIGHT or key == arcade.key.D:
            self.player_sprite.change_x = 0

def main():
    """主函数"""
    game = PlatformerGame()
    game.setup_level(1)
    arcade.run()

if __name__ == "__main__":
    main()